﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace NFox.Pycad
{
    public abstract class PluginBase : IEnumerable<PluginBase>
    {
        
        public string Name
        {
            get { return GetType().Namespace; }
        }

        public static PluginBase Root { get; protected set; }

        public static PluginBase GetPlugin(string name)
        {
            return Root.getPlugin(name);
        }

        private PluginBase getPlugin(string name)
        {
            if (Name == name) return this;
            foreach(var plugin in _lst)
            {
                var p = plugin.getPlugin(name);
                if (p != null)
                    return p;
            }
            return null;
        }

        public static Engine Engine { get; protected set;}

        public dynamic Parent { get; internal set; }

        public static Version Version { get; internal set; }


        private static Dictionary<string, dynamic> _systemvariables = 
            new Dictionary<string, dynamic>();

        public static void SetVariable(string key, dynamic value)
        {
            _systemvariables[key.ToUpper()] = value;
        }

        public static dynamic GetVariable(string key)
        {
            key = key.ToUpper();
            if(_systemvariables.ContainsKey(key))
                return _systemvariables[key];
            return null;
        }

        protected static Dictionary<string, dynamic> Values;

        public static dynamic GetValue(string name)
        {
            if (!Values.ContainsKey(name))
            {
                try
                {
                    Values[name] = Engine.Execute(name);
                }
                catch
                {
                    Engine.Import(name.Split('.')[0]);
                    Values[name] = Engine.Execute(name);
                }
            }
            return Values[name];
        }


        private List<PluginBase> _lst = new List<PluginBase>();

        protected virtual void OnLoaded() { }
        protected virtual void OnLoading() { }
        protected virtual void OnUnloading() { }
        protected virtual void OnUnloaded() { }

        public virtual void Initialize()
        {
            foreach (PluginBase child in _lst)
                child.Initialize();
        }

        public virtual void Terminate()
        {
            foreach (PluginBase child in _lst)
                child.Terminate();
        }

        public void Add(PluginBase p)
        {
            p.Parent = this;
            _lst.Add(p);
        }

        public void Remove(PluginBase p)
        {
            _lst.Remove(p);
        }

        public void Start()
        {
            try
            {
                OnLoading();
                foreach (PluginBase child in _lst)
                    child.OnLoading();
                OnLoaded();
                foreach (PluginBase child in _lst)
                    child.OnLoaded();
            }
            catch { }
        }

        public void End()
        {
            try
            {
                foreach (var child in _lst)
                    child.OnUnloading();
                OnUnloading();
                foreach (var child in _lst)
                    child.OnLoaded();
                OnLoaded();
            }
            catch { }
        }

        public virtual void SendMessage(string message)
        {
            foreach (var child in this)
                SendMessage(message);
        }

        public IEnumerator<PluginBase> GetEnumerator()
        {
            return _lst.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return _lst.GetEnumerator();
        }

    }

}
